#include "ZComDef.h"
#include "OSAL.h"
#include "hal_uart.h"
#include "OSAL_Memory.h"
#include "mfg.h"
#include "cmd_uart.h"
#include "ZComDef.h"

void cmd_UartHandleCB( uint8 port, uint8 event );
void cmd_UartRx( uint8 port );
void cmd_UartTx( uint8 port );

bool cmd_TxPush( cmd_uartTxList_t* item );

uint8 cmd_TaskId = 0xFF;

uint8 cmd_RxState = CMD_STATE_IDLE;
uint8 cmd_RxSize = 0;
uint8 cmd_LastChar = 0;

cmd_uartRxMsg_t* uartRxMsg = NULL;
cmd_uartTxList_t* uartTxList = NULL;

void cmd_uartInit(uint8 taskId)
{
  halUARTCfg_t uartConfig;

  /* Initialize APP ID */
  cmd_TaskId = taskId;

  /* UART Configuration */
  uartConfig.configured           = TRUE;
  uartConfig.baudRate             = HAL_UART_BR_57600;
  uartConfig.flowControl          = FALSE;
  uartConfig.flowControlThreshold = 32;
  uartConfig.rx.maxBufSize        = 64;
  uartConfig.tx.maxBufSize        = 64;
  uartConfig.idleTimeout          = 4;
  uartConfig.intEnable            = TRUE;
  uartConfig.callBackFunc         = cmd_UartHandleCB;
  HalUARTOpen (HAL_UART_PORT_0, &uartConfig);
}

void cmd_UartHandleCB ( uint8 port, uint8 event )
{
  if (event == HAL_UART_TX_EMPTY)
  {
    cmd_UartTx(port);
  }

  if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT))
  {
    cmd_UartRx(port);
  }
}

void cmd_UartRx(uint8 port)
{
  uint8 ch;
  if( HalUARTRead (port, &ch, 1) )
  {
    switch(cmd_RxState)
    {
    case CMD_STATE_IDLE:
      if( (cmd_LastChar == 0xA5) && (ch == 0x5A) )
      {
        cmd_RxState = CMD_STATE_START;
        cmd_LastChar = 0x00;
        break;
      }
      cmd_LastChar = ch;
      break;
      
    case CMD_STATE_START:
      {
        if( (uartRxMsg == NULL) && (ch >= 4 ) )
        {
          cmd_RxSize = ch;
          uartRxMsg = (cmd_uartRxMsg_t*)osal_msg_allocate(sizeof(cmd_uartRxMsg_t) + cmd_RxSize);
          if(uartRxMsg )
          {
            cmd_RxState = CMD_STATE_DATA;
            uartRxMsg->size = 0;
            break;
          }
        }
        cmd_RxState = CMD_STATE_ERRO;
      }
      break;
      
    case CMD_STATE_DATA:
      {
        uartRxMsg->data[uartRxMsg->size++] = ch;
        if(uartRxMsg->size >= cmd_RxSize)
        {
          uartRxMsg->hdr.event = SPI_INCOMING_ZAPP_DATA;
          uartRxMsg->hdr.status = ZSuccess;
          osal_msg_send( cmd_TaskId, (byte *)uartRxMsg );
          cmd_RxSize = 0;
          uartRxMsg = NULL;
          cmd_RxState = CMD_STATE_IDLE;
        }
      }
      break;
    }
  }
}

void cmd_UartTx(uint8 port)
{
  
}

void cmd_uartRxTimeout(void)
{
  cmd_RxState = CMD_STATE_IDLE;
  cmd_LastChar = 0x00;
  if( uartRxMsg )
  {
    osal_msg_deallocate( (uint8_t*)uartRxMsg );
    uartRxMsg = NULL;
  }
}

void cmd_uartTxTimeout(void)
{
  
}

bool cmd_uartSend(uint8_t* buff, uint16_t size)
{
  cmd_uartTxList_t* item = osal_mem_alloc(sizeof(cmd_uartTxList_t) + size);
  if( item )
  {
    item->next = NULL;
    item->size = size;
    osal_memcpy( item->data, buff, size );
    if( uartTxList == NULL )
    {
      uartTxList = item;
    }
    else
    {
      cmd_uartTxList_t* tail = uartTxList;
      while( tail->next )
      {
        tail = tail->next;
      }
      tail->next = item;
    }
    return TRUE;
  }
  return FALSE;
}
/*
bool cmd_TxSend( uint8 len, uint8* payload )
{
  
}
*/

bool cmd_TxPush( cmd_uartTxList_t* item )
{
  if( item )
  {
    item->next = NULL;
    //item->size = size;
    //osal_memcpy( item->data, buff, size );
    if( uartTxList == NULL )
    {
      uartTxList = item;
      return TRUE;
    }
    else
    {
      cmd_uartTxList_t* tail = uartTxList;
      while( tail->next )
      {
        tail = tail->next;
      }
      tail->next = item;
    }
  }
  return FALSE;
}

/*
bool cmd_uartSend(uint8_t* buff, uint16_t size)
{
  if(UART_STATUS_ERROR == UART_write(cmdUartHandle, buff, size))
  {
    return false;
  }
  return true;
}




void cmd_uartReadCallback(UART_Handle handle, void *buf, size_t count)
{
  MFG_CSState key;
  key = MFG_enterCS();
  //Input received data
  CmdPkt_RxInd(buf, count);
  //set next rx
  UART_read(cmdUartHandle, buf, CMD_UART_BUF_SIZE);
  MFG_leaveCS(key);
}

void cmd_uartWriteCallback(UART_Handle handle, void *buf, size_t count)
{
  MFG_CSState key;
  key = MFG_enterCS();
  CmdPkt_TxCnf(buf);
  MFG_leaveCS(key);
}
*/